package com.ruoyi.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.user.constant.QbUserConstant;
import com.ruoyi.user.domain.QbUser;
import com.ruoyi.user.domain.QbUserWx;
import com.ruoyi.user.mapper.QbUserMapper;
import com.ruoyi.user.service.IQbUserWxService;
import com.ruoyi.user.service.IqbUserService;
import com.ruoyi.user.util.QbDataUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;

/**
 * 人员-微信绑定关系Controller
 *
 * @author lzhj
 * @date 2021-01-19
 */
@Validated
@Api(tags = "人员-微信绑定关系管理")
@RestController
@RequestMapping("/qb/unauth/userwx")
public class QbUserWxController extends BaseController {
    @Autowired
    private IQbUserWxService qbUserWxService;
    @Autowired
    private IqbUserService qbUserService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysDictTypeService dictTypeService;

    private static Logger logger = LoggerFactory.getLogger(QbUserWxController.class);

    @Autowired
    HttpServletRequest httpServletRequest;

    /**
     * 小程序appId
     */
    @Value("${wx.xcx.appId:}")
    private String appId;

    /**
     * 小程序secret
     */
    @Value("${wx.xcx.secret:}")
    private String secret;
    @Autowired
    private QbUserMapper qbUserMapper;


    /**
     * 小程序API
     */
    private static final String XCX_AIP = "https://api.weixin.qq.com/sns/jscode2session";

    /**
     * 小程序获取openID
     *
     * @param code
     * @return
     */
    @ApiOperation(value = "小程序获取openID")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "code值", paramType = "query", required = true)
    })
    @GetMapping("getUserByWxCode")
    public AjaxResult getUserCode(@NotBlank String code) {
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(XCX_AIP + "?appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code", String.class);
        return AjaxResult.success("获取OPENID成功", responseEntity.getBody());
    }

    /**
     * 获得微信的菜单
     *
     * @return
     */
    @ApiOperation(value = "获得微信的菜单，用于是否显示对于的菜单，dictValue：菜单代码值")
    @GetMapping("getWxMenu")
    public AjaxResult getWxMenu() {
        List<SysDictData> menuData = dictTypeService.selectDictDataByType("wx_xcx_menu");
        return AjaxResult.success("获取成功", menuData);
    }

    /**
     * 获得人员类别数据
     *
     * @return
     */
    @ApiOperation(value = "获得人员类别数据")
    @GetMapping("getRylb")
    public AjaxResult getRylb() {
        List<SysDictData> menuData = dictTypeService.selectDictDataByType("bus_rylb");
        return AjaxResult.success("获取成功", menuData);
    }

    /**
     * 获得公告数据
     *
     * @return
     */
    @ApiOperation(value = "获得公告数据")
    @GetMapping("getNotice")
    public AjaxResult getNotice() {
        List<Map<String, Object>> notice = qbUserWxService.getNotice();
        return AjaxResult.success("获取成功", notice);
    }

    /**
     * 新增人员-微信绑定关系,
     */
    @ApiOperation(value = "新增人员-微信绑定关系", notes = "返回：token：token，后面的接口请求需要，qbUserList：人员信息：category人员类别（题库类别）。<br>code=-1，或qbUserList为空：判断账号未绑定")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "zjh", value = "证件号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "xm", value = "姓名", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "category", value = "类别", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "openId", value = "微信openID", dataType = "String", paramType = "query"),
    })
//    @PreAuthorize("@ss.hasPermi('qb:userwx:add')")
    @Log(title = "人员-微信绑定关系", businessType = BusinessType.INSERT)
    @PostMapping("/bindWx")
    public AjaxResult bindWx(@NotBlank(message = "证件号不能为空") String zjh,
                             @NotBlank(message = "姓名不能为空") String xm,
                             @NotBlank(message = "人员类型不能为空") String category,
                             @NotBlank(message = "openID不能为空") String openId) {
        JSONObject object = new JSONObject();
        //判断注册
        QbUser qbUser = qbUserService.getUserByZjhAndCategory(zjh, category, null);
          if (qbUser == null || !xm.equals(qbUser.getUserName())) {
            return AjaxResult.error("账号未注册");
        }
        //判断审核
        if (!QbUserConstant.USER_SHTG.equals(qbUser.getStatus())) {
            return AjaxResult.error("账号未通过审核，请联系管理员审核");
        }

        //判断绑定
        Boolean bindWx = qbUserWxService.isBindWx(qbUser.getId());
        if (bindWx) {
            return AjaxResult.error("账号已绑定微信,如需重新绑定，请联系管理员解绑");
        }
        QbUserWx qbUserWx = new QbUserWx();
        qbUserWx.setUserId(qbUser.getId());
        qbUserWx.setZjh(zjh);
        qbUserWx.setCategory(category);
        qbUserWx.setOpenId(openId);
//        qbUserWx.setCreateBy(SecurityUtils.getUsername());
        int i = qbUserWxService.insertQbUserWx(qbUserWx);
        if (i == 1) {
            List<QbUser> qbUsers = qbUserService.queryUserListByOpenid(openId);
            //设置微信绑定的用户的缓存
            redisCache.setCacheObject(QbDataUtil.getWxUserCacheKey(openId), qbUsers);
            //人员类别，前端根据有无人员类别（题库类别）判断是否已经绑定
            getRylbName(qbUsers);

//            AsyncManager.me().execute(AsyncFactory.recordLogininfor(zjh, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
            // 生成token
            LoginUser loginUser = new LoginUser();
            SysUser sysUser = new SysUser();
            sysUser.setUserId(qbUser.getId());
            sysUser.setUserName(qbUser.getZjh());
            sysUser.setNickName(qbUser.getUserName());
//        String password = SecurityUtils.encryptPassword(qbUser.getOpenId());
            sysUser.setPassword(openId);
            loginUser.setUser(sysUser);
            String token = tokenService.createToken(loginUser);
            object.put("token", token);
            object.put("code", "1");
            object.put("qbUserList", qbUsers);
            logger.info("微信绑定成功userid:" + qbUser.getId());
            return AjaxResult.success("绑定成功", object);
        } else {
            return AjaxResult.error("绑定失败，请联系管理员");
        }
    }

    /**
     * 微信通过openID获取用户信息
     */
    @ApiOperation(value = "微信通过openID获取用户信息", notes = "返回：token：token，后面的接口请求需要，qbUserList：人员信息：category人员类别（题库类别）。<br>code=-1，或qbUserList为空：判断账号未绑定")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "openId", value = "微信openID", dataType = "String", paramType = "query"),
    })
    @Log(title = "微信通过openID获取用户信息", businessType = BusinessType.OTHER)
    @PostMapping(value = "/getBindUserInfo")
    public AjaxResult getBindUserInfo(@NotBlank(message = "openID不能为空") String openId) {

        JSONObject object = new JSONObject();
        //获取微信绑定的用户的缓存
        List<QbUser> qbUsers = redisCache.getCacheObject(QbDataUtil.getWxUserCacheKey(openId));
        if (CollectionUtils.isEmpty(qbUsers)) {
            qbUsers = qbUserService.queryUserListByOpenid(openId);
            //设置微信绑定的用户的缓存
            redisCache.setCacheObject(QbDataUtil.getWxUserCacheKey(openId), qbUsers);
        }
        if (CollectionUtils.isEmpty(qbUsers)) {
            object.put("code", -1);
            return AjaxResult.success("请先绑定账号", object);
        }
        //人员类别，前端根据有无人员类别（题库类别）判断是否已经绑定
        getRylbName(qbUsers);
        QbUser qbUser = qbUsers.get(0);
        String zjh = qbUser.getZjh();
//        AsyncManager.me().execute(AsyncFactory.recordLogininfor(zjh, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        // 生成token
        LoginUser loginUser = new LoginUser();
        SysUser sysUser = new SysUser();
        sysUser.setUserId(qbUser.getId());
        sysUser.setUserName(qbUser.getZjh());
        sysUser.setNickName(qbUser.getUserName());
//        String password = SecurityUtils.encryptPassword(qbUser.getOpenId());
        sysUser.setPassword(openId);
        loginUser.setUser(sysUser);
        String token = tokenService.createToken(loginUser);
        object.put("token", token);
        object.put("code", "1");
        object.put("qbUserList", qbUsers);
        logger.info("微信小程序登录成功userid:" + qbUser.getId());
//        for (QbUser user : qbUsers) {
//            Map<String, Object> claims = new HashMap<>();
////                claims.put("user", user);
//            claims.put("userId", user.getId());
//            claims.put("openId", openId);
//            String token1 = createToken(claims);
//            System.out.println(token1);
////                getToken(httpServletRequest);
//            System.out.println(parseToken(token1).toString());
//        }
        return AjaxResult.success("获取用户信息成功", object);
    }

    /**
     * 微信登录
     */
    @ApiOperation(value = "微信登录", hidden = true)
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "zjh", value = "证件号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "xm", value = "姓名", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "category", value = "类别", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "openId", value = "微信openID", dataType = "String", paramType = "query"),
    })
    @Log(title = "微信登录", businessType = BusinessType.OTHER)
    @PostMapping(value = "/login")
    public AjaxResult login(@NotBlank(message = "证件号不能为空") String zjh,
                            @NotBlank(message = "姓名不能为空") String xm,
                            @NotBlank(message = "人员类型不能为空") String category,
                            @NotBlank(message = "openID不能为空") String openId) {

        JSONObject object = new JSONObject();
        //判断注册
        QbUser qbUser = qbUserService.getUserByZjhAndCategory(zjh, category, null);
        if (qbUser == null || !xm.equals(qbUser.getUserName())) {
            return AjaxResult.error("用户在该类别未注册");
        }
        Long userId = qbUser.getId();
        String zjh1 = qbUser.getZjh();
        //判断审核
        if (!QbUserConstant.USER_SHTG.equals(qbUser.getStatus())) {
            return AjaxResult.error("用户在该类别的审核未通过");
        }

        QbUserWx userWx = qbUserWxService.getQbUserWxByUserIdAndWx(userId, openId);
        if (userWx == null) {
            object.put("code", "-1");
            return AjaxResult.error("用户未绑定", object);
        }

        //获取微信绑定的用户的缓存
        List<QbUser> qbUsers = redisCache.getCacheObject(QbDataUtil.getWxUserCacheKey(openId));
        if (qbUsers == null) {
            qbUsers = qbUserService.queryUserListByOpenid(openId);
            //设置微信绑定的用户的缓存
            redisCache.setCacheObject(QbDataUtil.getWxUserCacheKey(openId), qbUsers);
        }
        //人员类别，前端根据有无人员类别（题库类别）判断是否已经绑定
        getRylbName(qbUsers);

//        AsyncManager.me().execute(AsyncFactory.recordLogininfor(zjh1, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        // 生成token
        LoginUser loginUser = new LoginUser();
        SysUser sysUser = new SysUser();
        sysUser.setUserId(qbUser.getId());
        sysUser.setUserName(qbUser.getZjh());
        sysUser.setNickName(qbUser.getUserName());
//        String password = SecurityUtils.encryptPassword(qbUser.getOpenId());
        sysUser.setPassword(openId);
        loginUser.setUser(sysUser);
        String token = tokenService.createToken(loginUser);
        object.put("token", token);
        object.put("code", "1");
        object.put("qbUserList", qbUsers);
        return AjaxResult.success("登录成功", object);
    }


    /**
     * 获取人员类别的字典表
     *
     * @param qbUserList
     * @return
     */
    private void getRylbName(List<QbUser> qbUserList) {
        List<SysDictData> rylbData = dictTypeService.selectDictDataByType("bus_rylb");
        if (CollectionUtils.isNotEmpty(qbUserList) && CollectionUtils.isNotEmpty(rylbData)) {
            for (QbUser user : qbUserList) {
                rylbData.forEach(e -> {
                    if (e.getDictValue().equals(user.getCategory())) {
                        user.setCategoryName(e.getDictLabel());
                    }
                });
            }
        }
    }



    /**
     * 获取请求token
     *
     * @param request
     * @return token
     */
    private String getToken(HttpServletRequest request)
    {
        String token = request.getHeader("");
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
        {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private Claims parseToken(String token)
    {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }



    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    private String createToken(Map<String, Object> claims)
    {
        String token = Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, secret).compact();
        return token;
    }


    //    /**
//     * 查询人员-微信绑定关系列表
//     */
//    @PreAuthorize("@ss.hasPermi('qb:userwx:list')")
//    @GetMapping("/list")
//    public TableDataInfo list(QbUserWx qbUserWx)
//    {
//        startPage();
//        List<QbUserWx> list = qbUserWxService.selectQbUserWxList(qbUserWx);
//        return getDataTable(list);
//    }
//
//    /**
//     * 导出人员-微信绑定关系列表
//     */
//    @PreAuthorize("@ss.hasPermi('qb:userwx:export')")
//    @Log(title = "人员-微信绑定关系", businessType = BusinessType.EXPORT)
//    @GetMapping("/export")
//    public AjaxResult export(QbUserWx qbUserWx)
//    {
//        List<QbUserWx> list = qbUserWxService.selectQbUserWxList(qbUserWx);
//        ExcelUtil<QbUserWx> util = new ExcelUtil<QbUserWx>(QbUserWx.class);
//        return util.exportExcel(list, "userwx");
//    }
//
//    /**
//     * 获取人员-微信绑定关系详细信息
//     */
//    @PreAuthorize("@ss.hasPermi('qb:userwx:query')")
//    @GetMapping(value = "/{id}")
//    public AjaxResult getInfo(@PathVariable("id") Long id)
//    {
//        return AjaxResult.success(qbUserWxService.selectQbUserWxById(id));
//    }


//    /**
//     * 修改人员-微信绑定关系
//     */
//    @ApiOperation("修改人员-微信绑定关系，qb:userwx:edit")
//    @PreAuthorize("@ss.hasPermi('qb:userwx:edit')")
//    @Log(title = "人员-微信绑定关系", businessType = BusinessType.UPDATE)
//    @PutMapping
//    public AjaxResult edit(@RequestBody QbUserWx qbUserWx)
//    {
//        return toAjax(qbUserWxService.updateQbUserWx(qbUserWx));
//    }

}
